package com.niit.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.niit.chat.common.Result;
import com.niit.chat.dto.SessionVO;
import com.niit.chat.entity.Message;
import com.niit.chat.entity.Session;
import com.niit.chat.entity.User;
import com.niit.chat.mapper.MessageMapper;
import com.niit.chat.mapper.SessionMapper;
import com.niit.chat.service.MessageService;
import com.niit.chat.service.UserService;
import com.niit.chat.utils.RedisMessageHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 消息服务实现类
 * 实现消息相关的业务逻辑
 */
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    private final SessionServiceImpl sessionService;
    private final UserService userService;
    private final SessionMapper sessionMapper;

    // 注入 Redis 消息处理器
    @Autowired
    private RedisMessageHandler redisMessageHandler;

    public MessageServiceImpl(SessionServiceImpl sessionService, UserService userService, SessionMapper sessionMapper) {
        this.sessionService = sessionService;
        this.userService = userService;
        this.sessionMapper = sessionMapper;
    }

    /**
     * 发送消息
     * 设置消息为未读状态并保存到数据库
     *
     * @param message 消息对象
     * @return 发送是否成功
     */

    @Override
    @Transactional
    public boolean sendMessage(Message message) {
        message.setIsRead(0);
        boolean result = save(message);

        if (result) {
            // 获取当前时间，用于会话维护
            java.time.LocalDateTime currentTime = java.time.LocalDateTime.now();
            
            // 1. 维护发送者的会话
            maintainSession(message.getSenderId(), message.getReceiverId());
            // 2. 维护接收者的会话
            maintainSession(message.getReceiverId(), message.getSenderId());

            // 通知发送者会话更新
            SessionVO senderSessionVO = new SessionVO();
            senderSessionVO.setId(message.getSenderId());
            senderSessionVO.setLastMessage(message.getContent());
            senderSessionVO.setLastMessageTime(currentTime);
            redisMessageHandler.notifySessionUpdated(senderSessionVO);
            
            // 通知接收者会话更新
            SessionVO receiverSessionVO = new SessionVO();
            receiverSessionVO.setId(message.getReceiverId());
            receiverSessionVO.setLastMessage(message.getContent());
            receiverSessionVO.setLastMessageTime(currentTime);
            redisMessageHandler.notifySessionUpdated(receiverSessionVO);
            
            // 通过WebSocket通知双方更新会话列表
            try {
                com.niit.chat.websocket.ChatWebSocketServer.notifySessionUpdate(message.getSenderId(), message.getReceiverId());
            } catch (Exception e) {
                log.error("WebSocket通知失败", e);
                // 通知失败不影响消息发送结果
            }
        }

        return result;
    }

    /**
     * 维护 tb_chat_session 表，保证 userId 和 friendId 之间有一条会话记录
     * lastMessage 只显示未撤回、未删除、未单方删除的最新消息
     */
    private void maintainSession(Long userId, Long friendId) {
        // 查询最新一条未撤回且未被删除的消息（包括单方删除）
        LambdaQueryWrapper<Message> msgWrapper = new LambdaQueryWrapper<>();
        msgWrapper.and(w -> w
                .eq(Message::getSenderId, userId).eq(Message::getReceiverId, friendId).eq(Message::getDeletedBySender, 0)
                .or()
                .eq(Message::getSenderId, friendId).eq(Message::getReceiverId, userId).eq(Message::getDeletedByReceiver, 0)
        )
        .eq(Message::getIsRecalled, 0)
        .eq(Message::getIsDeleted, 0)
        .orderByDesc(Message::getSendDate)
        .last("LIMIT 1");
        Message lastMsg = this.getOne(msgWrapper);

        String lastMessage = "";
        if (lastMsg != null) {
            if (lastMsg.getType() == 1) {
                lastMessage = "[图片]";
            } else if (lastMsg.getType() == 2) {
                lastMessage = "[视频]";
            } else {
                lastMessage = lastMsg.getContent();
            }
        }
        java.time.LocalDateTime lastMessageTime = lastMsg != null ? lastMsg.getSendDate() : null;

        // 获取好友昵称和头像
        String nickName = userService.getNicknameById(friendId).orElse("未知用户");
        String avatar = null;
        User friend = userService.getById(friendId);
        if (friend != null) {
            avatar = friend.getAvatar();
        }

        // 查询是否已有会话
        LambdaQueryWrapper<Session> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Session::getUserId, userId)
               .eq(Session::getFriendId, friendId); // 用 friend_id 字段存 friendId
        Session session = sessionMapper.selectOne(wrapper);

        if (session == null) {
            // 新建会话
            session = new Session();
            session.setUserId(userId);
            session.setFriendId(friendId);
            session.setNickName(nickName);
            session.setName("与" + nickName + "的聊天"); // 设置会话名称
            session.setAvatar(avatar);
            session.setLastMessage(lastMessage);
            session.setLastMessageTime(lastMessageTime);
            sessionService.createSession(session);
        } else {
            // 更新会话
            session.setLastMessage(lastMessage);
            session.setLastMessageTime(lastMessageTime);
            sessionService.updateSession(session);
        }
    }

    /**
     * 获取与指定用户的聊天历史记录
     * 使用分页查询，按时间倒序排列
     *
     * @param userId 当前用户ID
     * @param targetUserId 目标用户ID
     * @param page 页码
     * @param size 每页大小
     * @return 消息列表
     */
    @Override
    public List<Message> getChatHistory(Long userId, Long targetUserId, Integer page, Integer size) {
        Page<Message> messagePage = new Page<>(page, size);
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        // 查询两个用户之间的所有消息，过滤撤回和删除
        wrapper.and(w -> w
                .eq(Message::getSenderId, userId)
                .eq(Message::getReceiverId, targetUserId)
                .or()
                .eq(Message::getSenderId, targetUserId)
                .eq(Message::getReceiverId, userId)
        )
        .eq(Message::getIsRecalled, 0)
        .and(w -> w
            .not(
                x -> x.eq(Message::getSenderId, userId).eq(Message::getDeletedBySender, 1)
            )
            .not(
                x -> x.eq(Message::getReceiverId, userId).eq(Message::getDeletedByReceiver, 1)
            )
        )
        .orderByAsc(Message::getSendDate);
        return page(messagePage, wrapper).getRecords();
    }

    /**
     * 获取用户的未读消息数量
     * 统计接收者为当前用户且未读的消息数量
     *
     * @param userId 用户ID
     * @return 未读消息数量
     */
    @Override
    public Integer getUnreadCount(Long userId) {
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getReceiverId, userId)
               .eq(Message::getIsRead, 0);
        return Math.toIntExact(count(wrapper));
    }

    /**
     * 将指定消息标记为已读
     * 批量更新消息的已读状态
     *
     * @param messageIds 需要标记为已读的消息ID列表
     * @return 标记是否成功
     */
    @Override
    @Transactional
    public boolean markAsRead(List<Long> messageIds) {
        if (messageIds == null || messageIds.isEmpty()) {
            return false;
        }
        return update().set("is_read", 1)
                      .in("id", messageIds)
                      .update();
    }

    /**
     * 撤回消息（2分钟内）
     */
    @Transactional
    public Result<Boolean> recallMessage(Long messageId, Long userId) {
        Message msg = getById(messageId);
        if (msg == null || !msg.getSenderId().equals(userId)) return Result.error("消息不存在或无权限");
        java.time.Duration duration = java.time.Duration.between(msg.getSendDate(), java.time.LocalDateTime.now());
        if (duration.toMinutes() >= 2) return Result.error("已超过两分钟无法撤回");
        msg.setIsRecalled(1);
        boolean result = updateById(msg);
        
        if (result) {
            // 撤回后维护双方会话
            maintainSession(msg.getSenderId(), msg.getReceiverId());
            maintainSession(msg.getReceiverId(), msg.getSenderId());
            
            // 通过Redis通知双方消息已撤回
            redisMessageHandler.notifyMessageRecalled(msg.getSenderId(), msg.getReceiverId(), messageId);
            
            // // 重新获取并推送发送方的会话更新
            // SessionVO senderSession = sessionService.getSession(msg.getSenderId(), msg.getReceiverId());
            // if (senderSession != null) webSocketHandler.notifySessionUpdated(senderSession);

            // // 重新获取并推送接收方的会话更新
            // SessionVO receiverSession = sessionService.getSession(msg.getReceiverId(), msg.getSenderId());
            // if (receiverSession != null) webSocketHandler.notifySessionUpdated(receiverSession);
        }
        
        return result ? Result.success(true) : Result.error("撤回失败");
    }

    /**
     * 删除消息（单方删除）
     */
    @Transactional
    public boolean deleteMessage(Long messageId, Long userId) {
        Message msg = getById(messageId);
        if (msg == null) return false;
        boolean changed = false;
        if (msg.getSenderId().equals(userId)) {
            msg.setDeletedBySender(1);
            changed = true;
        } else if (msg.getReceiverId().equals(userId)) {
            msg.setDeletedByReceiver(1);
            changed = true;
        } else {
            return false;
        }
        boolean result = updateById(msg);
        // 删除后维护会话，防止最近消息显示已删除内容
        if (result && changed) {
            maintainSession(msg.getSenderId(), msg.getReceiverId());
            maintainSession(msg.getReceiverId(), msg.getSenderId());
        }
        return result;
    }

}